﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
using System.Drawing;
using System.IO;
using MDK.Winform;

namespace MDK.WebApi
{
    public class WebApiProxy
    {
        public bool IsRun { get; private set; }

        private HttpListener _http;

        private List<Type> _services;

        public WebApiProxy()
        {
            _services = this.GetType().Assembly.GetTypes().Where(t => t.Name.EndsWith("ApiController")).ToList();
        }

        public void Start(string port)
        {
            if(IsRun) return;
            IsRun = true;
            _http = new HttpListener();
            _http.Prefixes.Add($"http://*:{port}/");
            _http.Start();
            ThreadPool.QueueUserWorkItem(Listen);
        }

        public void Stop()
        {
            IsRun = false;
            _http.Stop();
        }

        private void Listen(object obj)
        {
            while (IsRun)
            {
                try
                {
                    var context = _http.GetContext();
                    ThreadPool.QueueUserWorkItem(Handler, context);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }

        private void Handler(object obj)
        {
            var context = obj as HttpListenerContext;

            if (context != null)
            {
                try
                {
                    var path = context.Request.RawUrl;
                    if(path == "/upload")
                    {
                        var argBuf = new byte[context.Request.ContentLength64];
                        var len = 0;
                        while(len < argBuf.Length)
                        {
                            len += context.Request.InputStream.Read(argBuf, len, argBuf.Length - len);
                        }
                       
                        using (MemoryStream ms1 = new MemoryStream(argBuf))
                        {
                            App.BitMap?.Dispose();
                            App.BitMap = (Bitmap)Image.FromStream(ms1);
                        }

                        context.Response.AddHeader("Access-Control-Allow-Origin", "*");
                        context.Response.ContentType = "application/json";
                        context.Response.ContentEncoding = Encoding.UTF8;
                        context.Response.StatusCode = (int)HttpStatusCode.OK;
                        context.Response.Close();
                    }
                    else
                    {
                        ProcessWebApi(context);
                    }
                }
                catch (Exception e)
                {
                    try
                    {
                        context.Response.ContentEncoding = Encoding.UTF8;
                        context.Response.StatusCode = 500;
                        var _500Buf = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject("HTTP 错误 500.0 - 服务器内部错误\r\n\r\n" + e.Message));
                        context.Response.ContentType = "application/json";
                        context.Response.ContentLength64 = _500Buf.Length;
                        context.Response.OutputStream.Write(_500Buf, 0, _500Buf.Length);
                        context.Response.Close();
                    }
                    catch (Exception)
                    {
                    }
                    
                }
            }
        }

        private void ProcessWebApi(HttpListenerContext context)
        {

            var path = context.Request.RawUrl;
            var parts = path.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
            var controllerName = parts.Length > 0 ? parts[0] : "";
            var actionName = parts.Length > 1 ? parts[1] : "";
            string content = "";
            if (context.Request.ContentLength64 > 0)
            {
                var argBuf = new byte[context.Request.ContentLength64];
                context.Request.InputStream.Read(argBuf, 0, argBuf.Length);
                content = Encoding.UTF8.GetString(argBuf);
            }

            var service = _services.Find(t => t.Name == controllerName + "ApiController");

            if (service != null)
            {
                var controller = Activator.CreateInstance(service);
                var action = controller.GetType().GetMethod(actionName);
                if (action != null)
                {
                    var param = action.GetParameters().FirstOrDefault();

                    var args = param == null ? new object[0] : new[] { JsonConvert.DeserializeObject(content, param.ParameterType) };

                    var result = action.Invoke(controller, args);

                    context.Response.AddHeader("Access-Control-Allow-Origin", "*");
                    context.Response.ContentType = "application/json";
                    context.Response.ContentEncoding = Encoding.UTF8;
                    var respBuf = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(result));
                    context.Response.StatusCode = (int)HttpStatusCode.OK;
                    context.Response.OutputStream.Write(respBuf, 0, respBuf.Length);
                    context.Response.Close();
                    return;
                }
            }

            context.Response.StatusCode = 404;
            var _404Buf = Encoding.UTF8.GetBytes("HTTP 错误 404.0 - Not Found");
            context.Response.ContentType = "application/json";
            context.Response.ContentLength64 = _404Buf.Length;
            context.Response.ContentEncoding = Encoding.UTF8;
            context.Response.OutputStream.Write(_404Buf, 0, _404Buf.Length);
            context.Response.Close();
        }
    }
}